#include "falling_things.hpp"
#include "bubles.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <GL/gl.h>
#include <GL/glut.h>
#include <GL/glext.h>
//эти постоянные контроллируют спавн летающих хреновин
//через скорость их генерации, и их плотность
#define NUM_THINGS_PER_SECOND 0.003
#define OBJECT_DENSITY 0.04
//а тут тупо размер области за пределом экрана - чтоб объекты
//невозникали из ниоткуда а плавно выезжали.
//но помоему оно не нужно. пусть будет 0
#define BORDER 0.0f
//квадрат от икса
inline double square(double x){return x*x;}

falling_things::falling_things(float w, float h):
	m_score(0),
	m_top(h+BORDER),
	m_bottom(-BORDER),
	m_left(-BORDER),
	m_right(w+BORDER),
	m_last_spawn_latency(0)
{
}
std::auto_ptr<falling_things::object> falling_things::create()
{
	//тупо добавляем шарик случайного размера в случайной точке верхней грани игрового поля
	float size=0.001*(random()%1000)*(MAX_OBJECT_SIZE-MIN_OBJECT_SIZE)+MIN_OBJECT_SIZE;
	float xpos=0.001*(random()%1000)*(m_right-m_left-2*size)+m_left+size;
	return std::auto_ptr<falling_things::object>(new buble(xpos, m_top+size-2.0, size));
}
void falling_things::paint()
{
	//поскольку сказано "на черном фоне", тут больше нихрена не будет. 
	glClearColor(0.0, 0.0, 0.0, 1.0);
	glClearDepth(1.0);
	glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
	//вот это надо сделать прямо здесь и сейчас
	//а то glut перестанет печатать буквы после шейдеров
	glRasterPos2f(5,5);
	//включим всякую лютую фигню
	glEnable(GL_DEPTH_TEST);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	//зададим проекционную матрицу тут 
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(m_left+BORDER, 
			m_right-BORDER,
			m_bottom+BORDER, 
			m_top-BORDER,
			2*MAX_OBJECT_SIZE,
			-2*MAX_OBJECT_SIZE);
}
void falling_things::post_paint()
{
	//отключим все лишнее
	glDisable(GL_DEPTH_TEST);
	glDisable(GL_BLEND);
	//и напечатаем очки побуквенно
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	char text[32];
	sprintf(text, "%u", m_score);
	for(int i=0;text[i];++i)
		glutBitmapCharacter(GLUT_BITMAP_9_BY_15, text[i]);

}
void falling_things::resize(float width, float height)
{
	//мы тут просто изменяем размеры игровой области
	m_top		=height+BORDER;
	m_bottom	=-BORDER;
	m_left		=-BORDER;
	m_right		=width+BORDER;
}
//проверка на видимость
bool falling_things::is_visible(float left, float bottom, float right, float top)
{
	
	if(left > m_right ||
	   right < m_left ||
	   top < m_bottom ||
	   bottom > m_top ) return false;
	return true;
}
void falling_things::animate(double dt)
{
	//может быть добавим сюда ветер
	//или картинку на заднем плане
}
void falling_things::mouse_motion(float dt, float& x, float& y, float dx, float dy)
{
	//x и y можно поправить если мы умеем скролиться
}
void falling_things::adjust_mouse_click(float& x, float& y)
{
	//x и y можно поправить если мы умеем скролиться
}
unsigned int falling_things::max_bubles_to_spawn(double dt)
{
	//мы следим, чтоб не создавать больше бублей в секунду
	//чем положено. эта функция скажет сколько можно спавнуть
	//бубликов за период, истекший с момента последнего спавна
	m_last_spawn_latency+=dt;
	unsigned int result=ceil(m_last_spawn_latency*NUM_THINGS_PER_SECOND);
	if(result>10)result=10;
	m_last_spawn_latency-=result;
	return result;
}
unsigned int falling_things::expected_number_of_bubles()
{
	//возвращает предельное колво бублей
	return ((m_top-m_bottom)*(m_right-m_left))/
			(square(MIN_OBJECT_SIZE*MAX_OBJECT_SIZE)*OBJECT_DENSITY);
}
